package whiteboard

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.view.MotionEvent
import android.view.View
import kotlin.math.abs

@SuppressLint("ViewConstructor")
@Suppress("unused")
class Graffiti(ctxt: Context, width: Int, height: Int): View(ctxt){
    private val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    private val canvas = Canvas(bitmap)
    private val savePen = arrayListOf<Pen>()
    private val delPen = arrayListOf<Pen>()
    private val SENSITIVITY = 6f
    private var shadow = false
    private var xStart = 0f
    private var yStart = 0f
    private var xMove = 0f
    private var yMove = 0f
    private lateinit var pen: Pen
    var pWidth = 3f
    var pColor = Color.RED
    var type = Type.LINE

    inner class Pen{
        val path = Path()
        val paint = Paint()
        init {
            paint.run{
                style = Paint.Style.STROKE
                strokeJoin = Paint.Join.ROUND
                strokeCap = Paint.Cap.ROUND
                isAntiAlias = true
                isDither = true
                strokeWidth = pWidth
                color = pColor
            }
        }
    }
    enum class Type{ LINE, RECT, CIRCLE }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(e: MotionEvent): Boolean {
        when(e.action){
            MotionEvent.ACTION_DOWN -> {
                xStart = e.rawX
                xMove = e.rawX
                yStart = e.rawY
                yMove = e.rawY
                pen = Pen()
                pen.path.moveTo(xStart, yStart)
            }
            MotionEvent.ACTION_MOVE -> {
                if(abs(e.rawX - xMove) > SENSITIVITY || abs(e.rawY - yMove) > SENSITIVITY) {
                    xMove = e.rawX
                    yMove = e.rawY
                    when (type) {
                        Type.LINE -> pen.path.quadTo(xMove, yMove, (xMove + e.rawX)/2, (yMove + e.rawY)/2)
                        Type.RECT -> {
                            pen.path.reset()
                            pen.path.addRoundRect(RectF(xStart, yStart, e.rawX, e.rawY), 1f, 1f, Path.Direction.CW)
                        }
                        Type.CIRCLE -> {
                            pen.path.reset()
                            pen.path.addOval(RectF(xStart, yStart, e.rawX, e.rawY), Path.Direction.CCW)
                        }
                    }
                }
            }
            MotionEvent.ACTION_UP -> {
                if(type == Type.LINE)
                    pen.path.lineTo(xMove, yMove)
                delPen.clear()
                savePen.add(pen)
                canvas.drawPath(pen.path, pen.paint)
            }
        }
        shadow = true
        invalidate()
        return true
    }

    override fun onDraw(cv: Canvas) {
        cv.drawBitmap(bitmap, 0f, 0f, null)
        if(shadow)
            cv.drawPath(pen.path, pen.paint)
    }

    fun undo(){
        if(savePen.isNotEmpty()){
            delPen.add(savePen.last())
            savePen.removeAt(savePen.lastIndex)
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
            savePen.forEach{ canvas.drawPath(it.path, it.paint) }
            shadow = false
            invalidate()
        }
    }

    fun redo(){
        if(delPen.isNotEmpty()){
            val pen = delPen.last()
            delPen.removeAt(delPen.lastIndex)
            savePen.add(pen)
            canvas.drawPath(pen.path, pen.paint)
            shadow = false
            invalidate()
        }
    }

    fun clear(){
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
        shadow = false
        invalidate()
        savePen.clear()
        delPen.clear()
    }
}
